/*******************************************************************
 *
 * Copyright (C), 2021-2022, LS, All rights reserved.
 *
 * Author      : 
 * Create Time : 2021-09-22
 * Version     : v0.1
 * Description : 
 *******************************************************************/
 
/*----------------------------Head file----------------------------*/
#include "hal_gpio.h"
#include "hal_display.h"
#include "user_config.h"

#define HAL_DISP_LOG_EN		0

#if HAL_DISP_LOG_EN
#include "log.h"
#define HAL_DISP_LOG		LOG_DEBUG
#else
#define HAL_DISP_LOG(...)
#endif


#define LCD_BL_OUTPUT_INIT()    hal_gpio_output_cfg(DISP_BL_EN_PIN_NUM, PULL_NULL)
#define LCD_BL_OUTPUT_LOW()     hal_gpio_write(DISP_BL_EN_PIN_NUM, 0)
#define LCD_BL_OUTPUT_HIGH()    hal_gpio_write(DISP_BL_EN_PIN_NUM, 1)

#define LCD_CS_OUTPUT_INIT()    hal_gpio_output_cfg(DISP_LCD_CS_PIN_NUM, PULL_NULL)
#define LCD_CS_OUTPUT_LOW()     hal_gpio_write(DISP_LCD_CS_PIN_NUM, 0)
#define LCD_CS_OUTPUT_HIGH()    hal_gpio_write(DISP_LCD_CS_PIN_NUM, 1)

#define LCD_WR_OUTPUT_INIT()    hal_gpio_output_cfg(DISP_LCD_WR_PIN_NUM, PULL_NULL)
#define LCD_WR_OUTPUT_LOW()     hal_gpio_write(DISP_LCD_WR_PIN_NUM, 0)
#define LCD_WR_OUTPUT_HIGH()    hal_gpio_write(DISP_LCD_WR_PIN_NUM, 1)

#define LCD_DATA_OUTPUT_INIT()  hal_gpio_output_cfg(DISP_LCD_DATA_PIN_NUM, PULL_NULL)
#define LCD_DATA_OUTPUT_LOW()   hal_gpio_write(DISP_LCD_DATA_PIN_NUM, 0)
#define LCD_DATA_OUTPUT_HIGH()  hal_gpio_write(DISP_LCD_DATA_PIN_NUM, 1)

#define LCD_PWR_OUTPUT_INIT()   
#define LCD_PWR_CTRL_ENABLE()   
#define LCD_PWR_CTRL_DISABLE()  

/*----------------------------type define--------------------------*/

/*----------------------------var define---------------------------*/
static bool disp_hw_init = false;
static bool disp_drv_init = false;
static bool disp_bl_on = false;

static const uint8_t lcd_init_cmd_seq[] = {
    0x52,	//Bias: 1/3, 4 COM
    0x30,	//Use internal RC
    0x02,	//SYS EN
    0x06	//LCD ON
};

static const uint8_t lcd_sleep_cmd_seq[] = {
    0x04, 	//LCD OFF
    0x00	//SYS DIS
};

static const uint8_t seg_valid_seq[SEGMENT_MAX_NUM] = {
    0, 1, 2, 3, 4, 5, 13, 14, 15, 16, 17, 18, 19, 26, 27, 28, 29, 30
};

/*-------------------------func declaration------------------------*/

/*-----------------------------------------------------------------*/

bool hal_disp_init_state_get(void)
{
    return disp_hw_init;
}

bool hal_disp_backlight_state_get(void)
{
    return disp_bl_on;
}

void hal_disp_backlight_set(bool enable)
{
    if(enable && false == disp_bl_on) {
        LCD_BL_OUTPUT_INIT();
        LCD_BL_OUTPUT_HIGH();
        disp_bl_on = true;
    }
    else if(!enable && disp_bl_on) {
        LCD_BL_OUTPUT_INIT();
        LCD_BL_OUTPUT_LOW();
        disp_bl_on = false;
    }
}


void hal_disp_drv_init(void)
{
    if(disp_drv_init)
        return;

    tm1621_sw_pin_init(DISP_LCD_WR_PIN_NUM, DISP_LCD_DATA_PIN_NUM);
    disp_drv_init = true;
}


void hal_disp_drv_deinit(void)
{
    if(false == disp_drv_init)
        return;

    LCD_CS_OUTPUT_INIT();
    LCD_WR_OUTPUT_INIT();
	LCD_DATA_OUTPUT_INIT();
    
    LCD_CS_OUTPUT_HIGH();
    LCD_WR_OUTPUT_HIGH();
    LCD_DATA_OUTPUT_HIGH();

    disp_drv_init = false;
}


void hal_disp_hw_init(void)
{
    if(true == disp_hw_init)
        return;

    LCD_PWR_OUTPUT_INIT();
    LCD_PWR_CTRL_ENABLE();
    app_delay_ms(100);
    
	LCD_CS_OUTPUT_INIT();
	LCD_CS_OUTPUT_HIGH();
	disp_hw_init = true;
}


void hal_disp_hw_deinit(void)
{
	hal_disp_drv_deinit();
	hal_disp_backlight_set(false);
    LCD_PWR_OUTPUT_INIT();
    LCD_PWR_CTRL_DISABLE();
	disp_hw_init = false;
}


void hal_disp_write_multi_cmd(const uint8_t *cmd, uint16_t len)
{
    LCD_CS_OUTPUT_LOW();
    tm1621_tx_bits_msb(0x80, 3);
    for(uint16_t i=0;i<len;i++) {
        tm1621_tx_bits_msb((cmd[i] >> 1), 9);
    }
    LCD_CS_OUTPUT_HIGH();
}


void hal_disp_write_disp_buffer(const uint8_t *buf, uint16_t len)
{
    if(len > SEGMENT_MAX_NUM)
        return;

    //Write continuously.
    uint8_t temp_seq = 0xFF;

    for(uint8_t i=0;i<len;i++)
    {
        if(temp_seq != seg_valid_seq[i*2]) {
            LCD_CS_OUTPUT_HIGH();
            LCD_CS_OUTPUT_LOW();
            tm1621_tx_bits_msb(0xA0, 3);
            tm1621_tx_bits_msb((seg_valid_seq[i*2] << 2), 6); //set addr
            temp_seq = seg_valid_seq[i*2];
        }
        
        tm1621_tx_bits_lsb(buf[i], 4);
        temp_seq++;

        if(temp_seq != seg_valid_seq[i*2+1])
        {
            LCD_CS_OUTPUT_HIGH();
            LCD_CS_OUTPUT_LOW();
            tm1621_tx_bits_msb(0xA0, 3);
            tm1621_tx_bits_msb((seg_valid_seq[i*2+1] << 2), 6); //set addr
            temp_seq = seg_valid_seq[i*2+1];
        }
        tm1621_tx_bits_lsb((buf[i] >> 4), 4);
        temp_seq++;
    }
    LCD_CS_OUTPUT_HIGH();


    //Write one data per addr.
    /*for(uint8_t i=0;i<len;i++) {
        hal_gpio_write(DISP_LCD_CS_PIN_NUM, 0);
        tm1621_tx_bits_msb(0xA0, 3);
        tm1621_tx_bits_msb((seg_valid_seq[i*2] << 2), 6); //set addr
        tm1621_tx_bits_lsb((buf[i] >> 4), 4);
        hal_gpio_write(DISP_LCD_CS_PIN_NUM, 1);
        if((i*2+1) < SEGMENT_MAX_NUM) {
            hal_gpio_write(DISP_LCD_CS_PIN_NUM, 0);
            tm1621_tx_bits_msb(0xA0, 3);
            tm1621_tx_bits_msb((seg_valid_seq[i*2+1] << 2), 6); //set addr
            tm1621_tx_bits_lsb(buf[i], 4);
            hal_gpio_write(DISP_LCD_CS_PIN_NUM, 1);
        }
    }*/
}

void hal_disp_cmd_init(void)
{
    hal_disp_write_multi_cmd(lcd_init_cmd_seq, sizeof(lcd_init_cmd_seq));
}

void hal_disp_sleep_enable(void)
{
    for(uint8_t i=0;i<3;i++) {
        hal_disp_write_multi_cmd(lcd_sleep_cmd_seq, sizeof(lcd_sleep_cmd_seq));
    }
}
